package handler

import (
	"context"
	"github.com/jinzhu/gorm"
	"github.com/micro/go-micro/v2/util/log"
	"gomicrodemo/changgou-goods-service/model"
	"gomicrodemo/changgou-goods-service/service"
	"gomicrodemo/common"
	"gomicrodemo/proto/goods"
	"time"
)

type handler struct {
	DBAgent service.DBAgent
}

func NewGoodHandler(db *gorm.DB) goods.GoodHandler {
	return handler{
		DBAgent: service.DBAgent{
			DB: db,
		},
	}
}

//商品上架
func (h handler) PutSpu(ctx context.Context, request *goods.PutSpuRequest, response *goods.PutSpuResponse) error {
	//根据商品Id查询该商品是否被删除，未删除则修改审核状态为已上架
	var spu model.Spu
	err := h.DBAgent.DB.Model(&model.Spu{}).Where("id = ?", request.SpuId).Find(&spu).Error
	if err != nil {
		log.Errorf("FindBySpuId fail, msg:%v", err.Error)
		response.BaseRsp, err = common.SetCommonRsp(err)
		return nil
	}
	//判断该商品是否存在，是否删除，是否下架
	if spu == (model.Spu{}) || spu.IsDelete == "" || spu.IsMarketable == "2" {
		response.BaseRsp.Code = 0
		response.BaseRsp.Msg = "该商品不符合上架要求"
		return nil
	}
	//符合条件更新状态为1

}

//新增商品
func (h handler) CreateSpu(ctx context.Context, request *goods.CreateSpuRequest, response *goods.CreateSpuResponse) error {
	spu, skuList := convertSpu(request)
	err := h.DBAgent.CreateSpu(spu, skuList)
	if err != nil {
		log.Infof("CreateSpu fail, msg:%v", err.Error)
		response.Code = -1
		response.Msg = err.Error()
		return nil
	}
	response.Code = 0
	response.Msg = "success"
	return nil
}

func (h handler) GetTemplates(ctx context.Context, request *goods.GetTemplatesRequest, response *goods.GetTemplatesResponse) error {
	templates, err := h.DBAgent.GetTemplates(request)
	if err != nil {
		log.Infof("GetTemplates fail, msg:%v", err)
		response.Code = -1
		response.Msg = err.Error()
		return nil
	}
	result := convertTemplates(templates)
	response.Templates = result
	response.Code = 0
	response.Msg = "success"
	return nil
}

func (h handler) UpdateTemplate(ctx context.Context, request *goods.UpdateTemplateRequest, response *goods.UpdateTemplateResponse) error {
	var template model.Template
	db := h.DBAgent.DB.Model(&template)
	db = db.Where("id = ?", request.Template.Id)
	value := convertTemplate(request.Template)
	if err := db.Updates(value).Error; err != nil {
		log.Infof("UpdateTemplate fail, msg:%v", err.Error())
		response.Code = -1
		response.Msg = err.Error()
		return nil
	}
	response.Code = 0
	response.Msg = "success"
	return nil
}

func (h handler) CreateTemplate(ctx context.Context, request *goods.CreateTemplateRequest, response *goods.CreateTemplateResponse) error {
	var template model.Template
	db := h.DBAgent.DB.Model(&template)
	db = db.Where("id = ?", request.Template.Id)
	value := convertTemplate(request.Template)
	if err := db.Create(value).Error; err != nil {
		log.Infof("CreateTemplate fail, msg:%v", err.Error())
		response.Code = -1
		response.Msg = err.Error()
		return nil
	}
	response.Code = 0
	response.Msg = "success"
	return nil
}

func (h handler) GetParams(ctx context.Context, request *goods.GetParamsRequest, response *goods.GetParamsResponse) error {
	params, err := h.DBAgent.GetParams(request)
	if err != nil {
		log.Infof("GetParams fail, msg:%v", err)
		response.Code = -1
		response.Msg = err.Error()
		return nil
	}
	result := convertParams(params)
	response.Params = result
	response.Code = 0
	response.Msg = "success"
	return nil
}

func (h handler) UpdateParam(ctx context.Context, request *goods.UpdateParamRequest, response *goods.UpdateParamResponse) error {
	var param model.Param
	db := h.DBAgent.DB.Model(&param)
	db = db.Where("id = ?", request.Param.Id)
	value := convertParam(request.Param)
	if err := db.Updates(value).Error; err != nil {
		log.Infof("UpdateParam fail, msg:%v", err.Error())
		response.Code = -1
		response.Msg = err.Error()
		return nil
	}
	response.Code = 0
	response.Msg = "success"
	return nil
}

func (h handler) CreateParam(ctx context.Context, request *goods.CreateParamRequest, response *goods.CreateParamResponse) error {
	var param model.Param
	db := h.DBAgent.DB.Model(&param)
	db = db.Where("id = ?", request.Param.Id)
	value := convertParam(request.Param)
	if err := db.Create(value).Error; err != nil {
		log.Infof("CreateParam fail, msg:%v", err.Error())
		response.Code = -1
		response.Msg = err.Error()
		return nil
	}
	response.Code = 0
	response.Msg = "success"
	return nil
}

func (h handler) GetSpecifications(ctx context.Context, request *goods.GetSpecificationsRequest, response *goods.GetSpecificationsResponse) error {
	specifications, err := h.DBAgent.GetSpecifications(request)
	if err != nil {
		log.Infof("GetGoods fail, msg:%v", err)
		response.Code = -1
		response.Msg = err.Error()
		return nil
	}
	result := convertSpecifications(specifications)
	response.Specifications = result
	response.Code = 0
	response.Msg = "success"
	return nil
}

func (h handler) UpdateSpecification(ctx context.Context, request *goods.UpdateSpecificationRequest, response *goods.UpdateSpecificationResponse) error {
	var specification model.Specification
	db := h.DBAgent.DB.Model(&specification)
	db = db.Where("id = ?", request.Specification.Id)
	value := convertSpecification(request.Specification)
	if err := db.Updates(value).Error; err != nil {
		log.Infof("UpdateSpecification fail, msg:%v", err.Error())
		response.Code = -1
		response.Msg = err.Error()
		return nil
	}
	response.Code = 0
	response.Msg = "success"
	return nil
}

func (h handler) CreateSpecification(ctx context.Context, request *goods.CreateSpecificationRequest, response *goods.CreateSpecificationResponse) error {
	var specification model.Specification
	db := h.DBAgent.DB.Model(&specification)
	db = db.Where("id = ?", request.Specification.Id)
	value := convertSpecification(request.Specification)
	if err := db.Create(value).Error; err != nil {
		log.Infof("CreateSpecification fail, msg:%v", err.Error())
		response.Code = -1
		response.Msg = err.Error()
		return nil
	}
	response.Code = 0
	response.Msg = "success"
	return nil
}

func (h handler) GetCategorys(ctx context.Context, request *goods.GetCategorysRequest, response *goods.GetCategorysResponse) error {
	categorys, err := h.DBAgent.GetCategorys(request)
	if err != nil {
		log.Infof("GetGoods fail, msg:%v", err)
		response.Code = -1
		response.Msg = err.Error()
		return nil
	}
	result := convertCategorys(categorys)
	response.Categorys = result
	response.Code = 0
	response.Msg = "success"
	return nil
}

func (h handler) UpdateCategory(ctx context.Context, request *goods.UpdateCategoryRequest, response *goods.UpdateCategoryResponse) error {
	var category model.Category
	db := h.DBAgent.DB.Model(&category)
	db = db.Where("id = ?", request.Category.Id)
	value := convertCategory(request.Category)
	if err := db.Updates(value).Error; err != nil {
		log.Infof("UpdateCategory fail, msg:%v", err.Error())
		response.Code = -1
		response.Msg = err.Error()
		return nil
	}
	response.Code = 0
	response.Msg = "success"
	return nil
}

func (h handler) CreateCategory(ctx context.Context, request *goods.CreateCategoryRequest, response *goods.CreateCategoryResponse) error {
	var specification model.Specification
	db := h.DBAgent.DB.Model(&specification)
	db = db.Where("id = ?", request.Category.Id)
	value := convertCategory(request.Category)
	if err := db.Create(value).Error; err != nil {
		log.Infof("CreateCategory fail, msg:%v", err.Error())
		response.Code = -1
		response.Msg = err.Error()
		return nil
	}
	response.Code = 0
	response.Msg = "success"
	return nil
}

func (h handler) UpdateBrands(ctx context.Context, request *goods.UpdateBrandsRequest, response *goods.UpdateBrandsResponse) error {

	value := convertBrand(request.Brand)
	_, updatedat := convertTime(time.Now(), time.Now())
	value.UpdatedAt = updatedat
	//value := make(map[string]interface{})
	//value["id"] = request.Brand.Id
	//value["name"] = request.Brand.Name
	//value["image"] = request.Brand.Image
	//value["letter"] = request.Brand.Letter
	//value["seq"] = request.Brand.Seq
	//value["updated_at"] = updatedat

	db := h.DBAgent.DB.Model(&model.Brand{})
	err := db.Where("id = ?", request.Brand.Id).Update(&value).Error
	if err != nil {
		log.Infof("UpdateBrands fail, msg:%v", err.Error())
		response.Code = -1
		response.Msg = err.Error()
		return nil
	}
	response.Code = 0
	response.Msg = "success"
	return nil
}

func (h handler) CreateBrands(ctx context.Context, request *goods.CreateBrandsRequest, response *goods.CreateBrandsResponse) error {
	var brand model.Brand
	db := h.DBAgent.DB.Model(&brand)
	db = db.Where("id = ?", request.Brand.Id)
	value := convertBrand(request.Brand)
	createdTime, updatedTime := convertTime(time.Now(), time.Now())
	value.CreatedAt = createdTime
	value.UpdatedAt = updatedTime
	if err := db.Create(value).Error; err != nil {
		log.Infof("CreateBrands fail, msg:%v", err.Error())
		response.Code = -1
		response.Msg = err.Error()
		return nil
	}
	response.Code = 0
	response.Msg = "success"
	return nil
}

func (h handler) GetBrands(ctx context.Context, request *goods.GetBrandsRequest, response *goods.GetBrandsResponse) error {
	brands, err := h.DBAgent.GetBrand(request)
	if err != nil {
		log.Infof("GetGoods fail, msg:%v", err)
		response.Code = -1
		response.Msg = err.Error()
		return nil
	}
	result := convertBrands(brands)
	response.Brands = result
	response.Code = 0
	response.Msg = "success"
	return nil
}

func convertBrands(brands []*model.Brand) []*goods.Brand {
	var result []*goods.Brand
	for _, v := range brands {
		var value = &goods.Brand{
			Id:     v.Id,
			Name:   v.Name,
			Image:  v.Image,
			Letter: v.Letter,
			Seq:    v.Seq,
		}
		result = append(result, value)
	}
	return result
}

func convertBrand(brands *goods.Brand) model.Brand {
	var value = model.Brand{
		Name:   brands.Name,
		Image:  brands.Image,
		Letter: brands.Letter,
		Seq:    brands.Seq,
	}
	return value
}

func convertTemplates(templates []*model.Template) []*goods.Template {
	var result []*goods.Template
	for _, v := range templates {
		var value = &goods.Template{
			Id:      v.Id,
			Name:    v.Name,
			SpecNum: v.SpecNum,
			ParaNum: v.ParaNum,
		}
		result = append(result, value)
	}
	return result
}

func convertTemplate(template *goods.Template) *model.Template {
	var value = &model.Template{
		Id:      template.Id,
		Name:    template.Name,
		SpecNum: template.SpecNum,
		ParaNum: template.ParaNum,
	}
	return value
}

func convertSpecifications(specifications []*model.Specification) []*goods.Specification {
	var result []*goods.Specification
	for _, v := range specifications {
		var value = &goods.Specification{
			Id:         v.Id,
			Name:       v.Name,
			Options:    v.Options,
			Seq:        v.Seq,
			TemplateId: v.TemplateId,
		}
		result = append(result, value)
	}
	return result
}

func convertSpecification(specification *goods.Specification) *model.Specification {
	var value = &model.Specification{
		Id:         specification.Id,
		Name:       specification.Name,
		Options:    specification.Options,
		Seq:        specification.Seq,
		TemplateId: specification.TemplateId,
	}
	return value
}

func convertParams(params []*model.Param) []*goods.Param {
	var result []*goods.Param
	for _, v := range params {
		var value = &goods.Param{
			Id:         v.Id,
			Name:       v.Name,
			Options:    v.Options,
			Seq:        v.Seq,
			TemplateId: v.TemplateId,
		}
		result = append(result, value)
	}
	return result
}

func convertParam(param *goods.Param) *model.Param {
	var value = &model.Param{
		Id:         param.Id,
		Name:       param.Name,
		Options:    param.Options,
		Seq:        param.Seq,
		TemplateId: param.TemplateId,
	}
	return value
}

func convertCategorys(categorys []*model.Category) []*goods.Category {
	var result []*goods.Category
	for _, v := range categorys {
		var value = &goods.Category{
			Id:         v.Id,
			Name:       v.Name,
			GoodsNum:   v.GoodsNum,
			IsShow:     v.IsShow,
			IsMenu:     v.IsMenu,
			Seq:        v.Seq,
			ParentId:   v.ParentId,
			TemplateId: v.TemplateId,
		}
		result = append(result, value)
	}
	return result
}

func convertCategory(category *goods.Category) *model.Category {
	var value = &model.Category{
		Id:         category.Id,
		Name:       category.Name,
		GoodsNum:   category.GoodsNum,
		IsShow:     category.IsShow,
		IsMenu:     category.IsMenu,
		Seq:        category.Seq,
		ParentId:   category.ParentId,
		TemplateId: category.TemplateId,
	}
	return value
}

//转换时间类型第一个参数对应第一个返回值，第二个参数对应第二个返回值，以此类推
func convertTime(createdat, updatedat time.Time) (time.Time, time.Time) {
	year, month, day := createdat.Date()
	createdat = time.Date(
		year, month, day, createdat.Hour(),
		createdat.Minute(), createdat.Second(),
		0, createdat.Location(),
	)

	year2, month2, day2 := updatedat.Date()
	updatedat = time.Date(
		year2, month2, day2, updatedat.Hour(),
		updatedat.Minute(), updatedat.Second(),
		0, updatedat.Location(),
	)
	return createdat, updatedat
}

func timeUnixToTime(unix int64) time.Time {
	dateTime := time.Unix(unix, 0)
	return dateTime
}

func convertSpu(spuRequest *goods.CreateSpuRequest) (*model.Spu, []*model.Sku) {

	insertSpu := &model.Spu{
		Sn:           spuRequest.Spu.Sn,
		Name:         spuRequest.Spu.Name,
		Caption:      spuRequest.Spu.Caption,
		BrandId:      spuRequest.Spu.BrandId,
		Category1Id:  spuRequest.Spu.Category1Id,
		Category2Id:  spuRequest.Spu.Category2Id,
		Category3Id:  spuRequest.Spu.Category3Id,
		TemplateId:   spuRequest.Spu.TemplateId,
		FreightId:    spuRequest.Spu.FreightId,
		Image:        spuRequest.Spu.Image,
		Images:       spuRequest.Spu.Images,
		SaleService:  spuRequest.Spu.SaleService,
		Introduction: spuRequest.Spu.Introduction,
		SpecItems:    spuRequest.Spu.SpecItems,
		ParaItems:    spuRequest.Spu.ParaItems,
		SaleNum:      spuRequest.Spu.SaleNum,
		CommentNum:   spuRequest.Spu.CommentNum,
		IsMarketable: "0",
		IsEnableSpec: spuRequest.Spu.IsEnableSpec,
		Status:       "0", //0待审核，1上架，2下架
	}
	var skuList []*model.Sku

	for _, sku := range spuRequest.SkuList {
		insertSku := model.Sku{
			Sn:           sku.Sn,
			Name:         sku.Name,
			Price:        sku.Price,
			Num:          sku.Num,
			AlertNum:     sku.AlertNum,
			Image:        sku.Image,
			Images:       sku.Images,
			Weight:       sku.Weight,
			CreateTime:   timeUnixToTime(sku.CreateTime),
			UpdateTime:   timeUnixToTime(sku.UpdateTime),
			SpuId:        sku.SpuId,
			CategoryId:   sku.CategoryId,
			CategoryName: sku.CategoryName,
			BrandName:    sku.BrandName,
			Spec:         sku.Spec,
			SaleNum:      sku.SaleNum,
			CommentNum:   sku.CommentNum,
			Status:       sku.Status,
		}
		skuList = append(skuList, &insertSku)
	}
	return insertSpu, skuList
}
